﻿using System.Linq;
using NUnit.Framework;
using PowerfulExtensions.Linq;

namespace PowerfulExtensions.Test
{
    [TestFixture]
    class LinqExtensionsTest
    {
        private MyClass[] _arr1;
        private MyClass[] _arr2;

        [SetUp]
        public void Setup()
        {
            _arr1 = new[]
            {
                new MyClass
                {
                    FloatField = 1.1f,
                    IntField = 1,
                    IntProp = 11,
                    StrField = "1",
                    StrProp = "11"
                },
                new MyClass
                {
                    FloatField = 1.1f,
                    IntField = 1,
                    IntProp = 11,
                    StrField = "1",
                    StrProp = "11"
                },
                new MyClass
                {
                    FloatField = 1.1f,
                    IntField = 2,
                    IntProp = 11,
                    StrField = "1",
                    StrProp = "12"
                },
            };

            _arr2 = new[] 
            {
                new MyClass
                {
                    FloatField = 2.3f,
                    IntField = 2,
                    IntProp = 22,
                    StrField = "1",
                    StrProp = "2"
                },
                new MyClass
                {
                    FloatField = 3.3f,
                    IntField = 3,
                    IntProp = 3,
                    StrField = "3",
                    StrProp = "33"
                },
                new MyClass
                {
                    FloatField = 1.1f,
                    IntField = 2,
                    IntProp = 11,
                    StrField = "1",
                    StrProp = "12"
                },
            };
        }

        [Test]
        public void ShouldReturn_Union_OfTwoIEnumerables()
        {
            var union = _arr1.Union(_arr2, c => c.IntField);
            Assert.AreEqual(3, union.Count());
        }

        [Test]
        public void ShouldReturn_Union_OfTwoIEnumerables_ComparedByTwoMembers()
        {
            var union = _arr1.Union(_arr2, c => c.IntField, c => c.FloatField);
            Assert.AreEqual(4, union.Count());
        }

        [Test]
        public void ShoudItarateThroughAllCollectionItems()
        {
            var arr = new[] { 1, 2, 3, 4 };
            var expectedSum = arr.Sum();
            int sum = 0;
            arr.Foreach(x => sum += x);
            Assert.AreEqual(expectedSum, sum);
        }

        [Test]
        public void ShouldRemove_DuplicatedItems_ComparedByMembers()
        {
            var distinctOneMember = _arr1.Distinct(c => c.StrProp);
            Assert.AreEqual(2, distinctOneMember.Count());

            var distinctTwoMembers = _arr1.Distinct(c => c.FloatField, c => c.IntField);
            Assert.AreEqual(2, distinctTwoMembers.Count());

            var distinctByMethod = _arr1.Distinct(c => c.IntFieldSquare());
            Assert.AreEqual(2, distinctByMethod.Count());
        }

        [Test]
        public void ShouldReturn_Intersection_OfTwoIEnumerables_ComparedByTwoMembers()
        {
            var intersection = _arr2.Intersect(_arr1, c => c.IntProp, c => c.StrField);
            Assert.AreEqual(1, intersection.Count());
        }

        [Test]
        public void ShouldReturn_SetDifferene_OfTwoIEnumerables_ComparedByTwoMembers()
        {
            var setDifference = _arr2.Except(_arr1, c => c.IntProp, c => c.StrField);
            Assert.AreEqual(2, setDifference.Count());
        }
    }
}
